package com.wechat.service.order.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fhMall.request.SubmitOrderRequest;
import com.fhMall.request.WechatOrderReturnHandleResquest;
import com.fhMall.response.SubmitOrderResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.wechat.core.exception.ServiceException;
import com.wechat.feign.FeignBaseService;
import com.wechat.feign.FhEmallOrderApi;
import com.wechat.models.response.FeignResult;
import com.wechat.service.order.WechatOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;


/**
 */
@Service
@Slf4j
public class WechatOrderServiceImpl implements WechatOrderService, FeignBaseService {

    @Autowired
    private FhEmallOrderApi fhEmallOrderApi;

    @Autowired
    private WxPayService wxPayService;

    @Value("${wechat.pay.notifyUrl}")
    private String payNotifyUrl;

    @Value("${wechat.refund.notifyUrl}")
    private String refundNotifyUrl;

    /**
     * 下订单
     * @param submitOrderRequest
     * @param openId
     * @param ipAddr
     * @return
     */
    @Override
    public JSONObject submitOrder(SubmitOrderRequest submitOrderRequest, String openId, String ipAddr) {
        String result = fhEmallOrderApi.submitOrder(submitOrderRequest);
        System.out.println(payNotifyUrl);
        SubmitOrderResponse response = toResponse(result, new TypeReference<FeignResult<SubmitOrderResponse>>() {});
        WxPayMpOrderResult payMpOrderResult;
        try {
            WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
                    .body("商品下单-支付")
                    .outTradeNo(response.getWechatPrepayId())
                    .totalFee(response.getPayPrice().multiply(BigDecimal.valueOf(100)).intValue())
                    .tradeType(WxPayConstants.TradeType.JSAPI)
                    .openid(openId)
                    .notifyUrl(payNotifyUrl)
                    .spbillCreateIp(ipAddr)
                    .timeStart(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
                    .build();
            payMpOrderResult = wxPayService.createOrder(wxPayUnifiedOrderRequest);

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            log.error("微信支付失败！订单：{},原因:{}", response, e.getMessage());
            throw new ServiceException("微信支付失败," + e.getMessage());
        }
        JSONObject object = new JSONObject(BeanUtil.beanToMap(payMpOrderResult));
        object.put("orderId", response.getOrderId());
        return object;
    }

    @Override
    public JSONObject payAgain(Integer orderId, Integer memberId, String openId, String ipAddr) {
        String result = fhEmallOrderApi.payAgain(orderId,memberId);
        System.out.println(payNotifyUrl);
        SubmitOrderResponse response = toResponse(result, new TypeReference<FeignResult<SubmitOrderResponse>>() {});
        WxPayMpOrderResult payMpOrderResult;
        try {
            WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
                    .body("商品下单-支付")
                    .outTradeNo(response.getWechatPrepayId())
                    .totalFee(response.getPayPrice().multiply(BigDecimal.valueOf(100)).intValue())
                    .tradeType(WxPayConstants.TradeType.JSAPI)
                    .openid(openId)
                    .notifyUrl(payNotifyUrl)
                    .spbillCreateIp(ipAddr)
                    .timeStart(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
                    .build();
            payMpOrderResult = wxPayService.createOrder(wxPayUnifiedOrderRequest);

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            log.error("微信支付失败！订单：{},原因:{}", response, e.getMessage());
            throw new ServiceException("微信支付失败," + e.getMessage());
        }
        JSONObject object = new JSONObject(BeanUtil.beanToMap(payMpOrderResult));
        object.put("orderId", response.getOrderId());
        return object;
    }

    /**
     * 退款
     * @param wechatOrderReturnHandleResquest
     * @return
     */
    @Override
    public JSONObject handleRefund(WechatOrderReturnHandleResquest wechatOrderReturnHandleResquest) {

        WxPayRefundResult wxPayRefundResult;
        try {
            WxPayRefundRequest wxPayRefundRequest = WxPayRefundRequest.newBuilder()
                    .transactionId(wechatOrderReturnHandleResquest.getTransactionId())
                    .outTradeNo(wechatOrderReturnHandleResquest.getWechatPrepayId())
                    .outRefundNo(wechatOrderReturnHandleResquest.getOrderReturnId().toString())
                    .totalFee(wechatOrderReturnHandleResquest.getPayOrderPrice().multiply(BigDecimal.valueOf(100)).intValue())
                    .refundFee(wechatOrderReturnHandleResquest.getPayPrice().multiply(BigDecimal.valueOf(100)).intValue())
                    .notifyUrl(refundNotifyUrl)
                    .build();

            wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
        } catch (Exception e) {
            log.error("微信退款失败！订单：{},原因:{}", wechatOrderReturnHandleResquest, e.getMessage());
            throw new ServiceException("微信退款失败," + e.getMessage());
        }
        JSONObject object = new JSONObject(BeanUtil.beanToMap(wxPayRefundResult));
        object.put("orderId", wechatOrderReturnHandleResquest.getOrderId());
        return object;
    }

    /**
     * 支付成功通知
     * @param paySuccessResult
     * @return
     */
    @Override
    public String paySuccess(String paySuccessResult) {
        log.info("支付通知，数据:" + paySuccessResult);
        try {
            WxPayOrderNotifyResult wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(paySuccessResult);
            if("SUCCESS".equals(wxPayOrderNotifyResult.getResultCode())){
                fhEmallOrderApi.paySuccess(wxPayOrderNotifyResult.getOutTradeNo(), wxPayOrderNotifyResult.getTransactionId());
                return  WxPayNotifyResponse.success("OK");
            }
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return  WxPayNotifyResponse.fail("");
    }

    /**
     * 退款成功通知
     * @param refundSuccessResult
     * @return
     */
    @Override
    public String refundSuccess(String refundSuccessResult) {
        log.info("退款通知，数据:" + refundSuccessResult);
        try {
            WxPayRefundNotifyResult wxPayRefundNotifyResult = wxPayService.parseRefundNotifyResult(refundSuccessResult);
            WxPayRefundNotifyResult.ReqInfo reqInfo = wxPayRefundNotifyResult.getReqInfo();
            if("SUCCESS".equals(wxPayRefundNotifyResult.getReqInfo().getRefundStatus())){
                fhEmallOrderApi.refundSuccess(reqInfo.getOutRefundNo(), reqInfo.getOutTradeNo(), reqInfo.getTransactionId());
                return  WxPayNotifyResponse.success("OK");
            }
        } catch (WxPayException e) {
            e.printStackTrace();
        }
        return  WxPayNotifyResponse.fail("");
    }


}
